/*-------------------------------------------------------------------------------
* file:     app_flashlog.c
* brief:    application
* copyright Copyright (C) 2020-2022 @ NanoIC
* Date:     2023-10-18
* Version:  V1.00
* Author:   JMH
*-------------------------------------------------------------------------------*/

/* include ----------------------------------------------------------------*/
#include "app_flash_log.h"

/* externs function--------------------------------------------------------*/

/* externs variablesr------------------------------------------------------*/
extern uint8_t one_wire_temp_ack_buf[ONE_WIRE_BUS_TEMP_ACK_BUF_LEN];
extern uint8_t one_wire_temp_ack_len;

/* Private variablesr------------------------------------------------------*/
//计时tick
volatile uint16_t golbal_flash_log_tiner_tick;
//log计时标志
volatile uint8_t golbal_flash_log_flag;
//备份log内容
uint8_t golbal_flash_log_buf[LIST_QUEUE_MAX_NUM];
//队列结构体
ListQueueStrust flash_log_queue;
//flash写的页数
uint8_t golbal_flash_log_page_num;
//flash中所有数据长度
volatile uint16_t golbal_log_len_num;

// uint8_t buf_fl[256];
uint8_t global_log_timer_buf[6] = {0x23,0x12,0x27,0x01,0x01,0x01};

/* Private function--------------------------------------------------------*/

/**
 * @brief 接收pad获取log相关信息
 * 
 * @param p_rec_packet 接收结构体
 * @return true 成功
 * @return false 失败
 */
bool one_wrie_bus_app_rec_flash_log_cmd(SourcePacketStr *p_rec_packet)
{
    bool ret;
    one_wire_temp_ack_len = 0x00;
    #if APP_FLASH_LOG_DEBUG_LOG
        printf("logrec =");
        console_log_num_byte(&p_rec_packet->data[0],p_rec_packet->len);
    #endif
    ret = app_flash_data_analysis(&p_rec_packet->data[0],&one_wire_temp_ack_buf[one_wire_temp_ack_len]);
    if(one_wire_temp_ack_buf[one_wire_temp_ack_len + 1] > 0)
    {
        one_wire_temp_ack_len += one_wire_temp_ack_buf[one_wire_temp_ack_len + 1] + 2;
    }
    #if APP_FLASH_LOG_DEBUG_LOG
        printf("logsend =");
        console_log_num_byte(one_wire_temp_ack_buf,one_wire_temp_ack_len);
    #endif
//    one_wire_bus_tra_write_long_frame_to_queue(one_wire_temp_ack_buf, one_wire_temp_ack_len, ONE_WIRE_BUS_CMD_READ_FLASH_LOG_DEV_ACK,0,true);
    return ret;
}

/**
 * @brief 接收数据解析
 * 
 * @param rx_data 接收数据
 * @param pack 回复的数据
 * @return true ；成功
 * @return false 失败
 */
bool app_flash_data_analysis(uint8_t * rx_data, uint8_t *pack)
{
    switch(rx_data[0])
    {
        case FLASH_LOG_STAR_CMD:
            golbal_log_len_num = app_flash_log_find_page(&flash_log_queue);
            //pad获取log开始
            pack[0] = rx_data[0];                       // ack_item_cmd
            pack[1] = 0x03;                             // ack_item_len
            pack[2] = rx_data[2];  
            pack[3] = golbal_log_len_num&0xff;   
            pack[4] = (golbal_log_len_num>>8)&0xff; 
            break;
        case FLASH_LOG_TRA_DATA_CMD:
            //获取log
            pack[0] = rx_data[0];               // ack_item_cmd
            pack[1] = rx_data[4]+3;             // ack_item_len
            pack[2] = 0x00;         //status
            pack[3] = rx_data[2];
            pack[4] = rx_data[3];
            uint16_t offset_l = rx_data[2] + (rx_data[3]<<8);
            if(offset_l == 0x00)
            {
                golbal_log_len_num = app_flash_log_find_page(&flash_log_queue);
            }
            
            if(((offset_l + rx_data[4]) > golbal_log_len_num) || rx_data[4] > 64)
            {
                pack[2] = 0x01;
            }
            #if APP_FLASH_LOG_DEBUG_LOG
                printf("offset_l = %x len=%d\n",offset_l,rx_data[4]);
            #endif
            app_flash_log_pad_get_log(offset_l,rx_data[4],(uint8_t*)&pack[5],&flash_log_queue);
            break;
        case FLASH_LOGG_END_CMD:
            pack[0] = rx_data[0];               // ack_item_cmd
            pack[1] = 0x01;             // ack_item_len
            pack[2] = 0x00;
            break;
        case FLASH_LOGG_GET_TIMER_CMD:
            memset(global_log_timer_buf,0,sizeof(global_log_timer_buf));
            memcpy(global_log_timer_buf,&rx_data[2],6);
            app_flash_log_16_to_10((uint8_t *)&global_log_timer_buf[0]);
            pack[0] = rx_data[0];               // ack_item_cmd
            pack[1] = 0x01;                     // ack_item_len
            if(global_log_timer_buf[0] == 0x00 && global_log_timer_buf[1] == 0x00)
            {
                pack[2] = 0x01;
            }else
            {
                pack[2] = 0x00;
            }
            pack[2] = 0x00;
            #if APP_FLASH_LOG_DEBUG_LOG
                printf("timer = ");
                console_log_num_byte(global_log_timer_buf,6);
            #endif
            break;
        default:
            pack[0] = 0x00;// ack_item_cmd
            pack[1] = 0x00;// ack_item_len
            pack[2] = 0x00;// ack_item_datal
            pack[3] = 0x00;// ack_item_datah
            break;
    }
    return true;
}

/**
 * @brief flash log初始化
 * 
 */
void app_flash_log_init(void)
{
    golbal_flash_log_tiner_tick = 0x00;
    golbal_flash_log_flag = 0x00;
    golbal_flash_log_page_num = 0x00;
    golbal_log_len_num = 0;
    for(uint16_t i = 0; i < LIST_QUEUE_MAX_NUM; i++)
    {
        golbal_flash_log_buf[i] = 0x00;
    }
    list_queue_create(&flash_log_queue,(uint8_t*)&golbal_flash_log_buf[0],LIST_QUEUE_MAX_NUM);
    
    if(golbal_flash_log_page_num >= 64)
    {
        app_flash_log_erase_addr(&flash_log_queue);
    }
    golbal_log_len_num = app_flash_log_find_page(&flash_log_queue);
    #if APP_FLASH_LOG_DEBUG_LOG
        // printf("golbal_log_len_num = %x\n",golbal_log_len_num);
    #endif
}


void app_flash_log_16_to_10(uint8_t * in_buf)
{
    uint8_t temp_buf[6] = {0};
    uint8_t i = 0;
    for(i = 0; i < 6; i++)
    {
        temp_buf[i] = in_buf[i];
    }
    
    uint8_t timer = 0x00;

    for (i = 0; i < 6; i++)
    {
        timer = ((temp_buf[i]/10) << 4) & 0xf0;;
        timer += ((temp_buf[i]%10) & 0x0f);
        in_buf[i] = timer;
    }
}

/**
 * @brief 上报log内容
 * 
 * @param offset 绝对偏移地址
 * @param data_len 获取数据长度
 */
void app_flash_log_pad_get_log(uint16_t offset, uint8_t data_len, uint8_t *read_buf, ListQueueStrust * q)
{
    int16_t flash_log_len_num_find = 0x00;
    uint16_t i = 0;

    //flash里的总长度
    flash_log_len_num_find = golbal_log_len_num - q->list_queue_num;
    if(flash_log_len_num_find <= 0)
    {
        flash_log_len_num_find = 0x00;
    }
    
    if(flash_log_len_num_find == 0x00)
    {
        //如果只有队列有数据
        for(i = 0; i < data_len; i++)
        {
            read_buf[i] = golbal_flash_log_buf[i+offset];
        }
    }else
    {
        //如果flash和队列都有数据，先打印flash数据，再打印队列数据
        if((offset + data_len) <= flash_log_len_num_find)
        {
            //如果当前获取数据大小都存在flash
            app_iwt_clr();
            app_spi_flash_page_read(FLASH_LOG_ADDR_STAR + offset,(uint8_t *)&read_buf[0],data_len);
            app_iwt_clr();
        }else
        {
            //如果当前获取的数据大小交叉存在flash和队列中，先获取flash数据，在获取队列数据。
            if(offset > flash_log_len_num_find)
            {
                //已经获取完flash数据，正在获取队列数据
                uint16_t q_len = offset - flash_log_len_num_find;
                for(i = 0; i < data_len; i++)
                {
                    read_buf[i] = golbal_flash_log_buf[i+q_len];
                }
            }else
            {
                //获取交叉数据
                uint16_t r_len = flash_log_len_num_find - offset;
                app_iwt_clr();
                app_spi_flash_page_read(FLASH_LOG_ADDR_STAR + offset,(uint8_t *)&read_buf[0],r_len);
                app_iwt_clr();
                uint16_t x_len = data_len - r_len;
                for(i = 0; i < x_len; i++)
                {
                    read_buf[i + r_len] = golbal_flash_log_buf[i];
                }
            }
        }
    }
}

/**
 * @brief 查询flash数据的大小
 * 
 * @return uint16_t 返回log的具体长度
 */
uint16_t app_flash_log_find_page(ListQueueStrust * q)
{
    uint8_t temp_buf[256] = {0};
    uint16_t timeout_tick = 0x00;
    uint16_t log_len_number = 0x00;
    uint8_t flash_log_page_num = 0x00;
    while(1)
    {
        app_iwt_clr();
        app_spi_flash_page_read(FLASH_LOG_ADDR_STAR + (flash_log_page_num * 256),temp_buf,10);
        if((temp_buf[0] == 0xff)&&(temp_buf[1] == 0xff)&&(temp_buf[5] == 0xff))
        {
            //判断数据是否是空白flash页标志
            if(flash_log_page_num == 0)
            {
                #if APP_FLASH_LOG_DEBUG_LOG
                    // printf("on data\n");
                #endif
                break;
            }
            break;
        }
        if(timeout_tick >= FLASH_LOG_MAX_PAGE_COUNT)
        {
            #if APP_FLASH_LOG_DEBUG_LOG
                // printf("timer out\n");
            #endif
            return 0;
        }
        timeout_tick ++;
        flash_log_page_num ++;
    }
    golbal_flash_log_page_num = flash_log_page_num;
    //读取最后一页
    if(flash_log_page_num != 0x00)
    {
        app_iwt_clr();
        app_spi_flash_page_read(FLASH_LOG_ADDR_STAR + ((flash_log_page_num-1) * 256),temp_buf,256);
        app_iwt_clr();
        uint16_t i;
        //遍历最后的数据位置
        for(i = 0; i < LIST_QUEUE_MAX_BUF_NUM; i++)
        {
            if(temp_buf[i] == 0xff)
            {
                #if APP_FLASH_LOG_DEBUG_LOG
                    // printf("i = %d\n",i);
                #endif
                log_len_number = (LIST_QUEUE_MAX_BUF_NUM*(golbal_flash_log_page_num-1))+i;
                log_len_number = log_len_number + q->list_queue_num;
                return log_len_number;
            }
        }
    }
    log_len_number = LIST_QUEUE_MAX_BUF_NUM*(golbal_flash_log_page_num);
    log_len_number = log_len_number + q->list_queue_num;
    #if APP_FLASH_LOG_DEBUG_LOG
        printf("log_len_number = %d\n",log_len_number);
    #endif
    return log_len_number;
}

/**
 * @brief 擦除log空间
 * 
 * @param q 队列指针
 */
void app_flash_log_erase_addr(ListQueueStrust * q)
{
    app_iwt_clr();
    app_spi_flash_sector_or_block_erase(FLASH_LOG_ADDR_STAR,FLASH_BLOCK32_SIZE);
    app_iwt_clr();
    golbal_flash_log_page_num = 0x00;
    q->list_queue_num = 0;
    q->head = 0x00;
    q->tail = 0x00;
}

/**
 * @brief log 进程
 * 
 */
void app_flash_log_process(void)
{
    if(!golbal_flash_log_flag)
        return;
    golbal_flash_log_flag = 0x00;
    uint16_t queue_len = list_queue_is_full(&flash_log_queue);
    if(!queue_len)    //是否写flash
        return;
    if(app_spi_flash_busy())                    //spi是否空闲
        return;
    uint8_t temp_buf[LIST_QUEUE_MAX_BUF_NUM] = {0};
    if(list_queue_read(&flash_log_queue,temp_buf,LIST_QUEUE_MAX_BUF_NUM) == false)//读出队列内容
        return;
    if(golbal_flash_log_page_num >= FLASH_LOG_MAX_PAGE_COUNT)  //flash空间是否足够
        return;
    app_iwt_clr();
    app_spi_flash_page_write(FLASH_LOG_ADDR_STAR + (golbal_flash_log_page_num * 256),temp_buf,LIST_QUEUE_MAX_BUF_NUM);
    // uint16_t len_data = app_spi_flash_save_log(FLASH_LOG_ADDR_STAR + ((golbal_flash_log_page_num) * 256),temp_buf,queue_len);
    app_iwt_clr();
    #if APP_FLASH_LOG_DEBUG_LOG
        printf("golbal_flash_log_page_num = %d\n",golbal_flash_log_page_num);
        printf("write socess\n");
    #endif
}

//------------------------------------------------------------------------------------
/**
 * @brief 打印函数  
 * 
 * @param char_buf 打印字符串指针
 * @param data_buf 打印数据指针
 * @param data_len 打印数据长度
 */
void app_flash_log_printf(char * char_buf,uint8_t * data_buf,uint16_t data_len)
{
    uint8_t flash_write_buf[100] = {0};
    int len;
    uint16_t i = 0;
    uint16_t lengh = 0,log_lengh = 0;
    uint32_t psr = 0x00;

    if((char_buf == NULL) && (data_buf != NULL))
        return;
    psr = csi_irq_save();

    hex_to_asciistring(global_log_timer_buf,6,(uint8_t *)&flash_write_buf[0]);

    len = strlen(char_buf);
    if(char_buf != NULL)
    {    
        for(i = 0; i < len; i++)
        {
            flash_write_buf[i+12] = char_buf[i];
        }
    }
    if(data_buf != NULL)
    {
        hex_to_asciistring(data_buf,data_len,(uint8_t *)&flash_write_buf[len + 12]);
    }

    lengh = flash_log_queue.list_queue_end_num - flash_log_queue.list_queue_num;
    log_lengh = (data_len * 2) + len + 12;
    flash_write_buf[log_lengh ++] = '\n';
    csi_irq_restore(psr);
    if(lengh > log_lengh) 
    {
        list_queue_write(&flash_log_queue,(uint8_t *)&flash_write_buf[0],log_lengh);
    }
}

//------------------------------------------------------------------------------------
void hex_to_asciistring(uint8_t* str,uint32_t size,uint8_t* str1)
{
    uint8_t deposit[2];
    uint16_t i=0;
    uint8_t j = 0;

    for(i=0;i<size;i++)
    {
        deposit[1] = str[i] & 0x0F;
        deposit[0] = (str[i] &0xF0) >> 4;
        for(j = 0; j < 2; j++)
        {
            switch(deposit[j])
            {
                case 0x00:
                    str1[i*2+j]='0';
                    break;
                case 0x01:
                    str1[i*2+j]='1';
                    break;
                case 0x02:
                    str1[i*2+j]='2';
                    break;
                case 0x03:
                    str1[i*2+j]='3';
                    break;
                case 0x04:
                    str1[i*2+j]='4';
                    break;
                case 0x05:
                    str1[i*2+j]='5';
                    break;
                case 0x06:
                    str1[i*2+j]='6';
                    break;
                case 0x07:
                    str1[i*2+j]='7';
                    break;
                case 0x08:
                    str1[i*2+j]='8';
                    break;
                case 0x09:
                    str1[i*2+j]='9';
                    break;
                case 0x0A:
                    str1[i*2+j]='A';
                    break;
                case 0x0B:
                    str1[i*2+j]='B';
                    break;
                case 0x0C:
                    str1[i*2+j]='C';
                    break;
                case 0x0D:
                    str1[i*2+j]='D';
                    break;
                case 0x0E:
                    str1[i*2+j]='E';
                    break;
                case 0x0F:
                    str1[i*2+j]='F';
                    break;
                default:
                    return;
            }
        }
    }
    return;
}

//------------------------------------------------------------------------------------
/**
 * @brief 创建队列
 * 
 * @param q 队列指针
 * @param p_buf 内存
 * @param list_queue_len 长度
 * @return true 
 * @return false 
 */
bool list_queue_create(ListQueueStrust * q, uint8_t *p_buf, uint16_t list_queue_len) 
{
    if((list_queue_len > LIST_QUEUE_MAX_NUM) || (list_queue_len < 3))
    {
        return false;
    }
    q->qu = p_buf;
    q->head = 0;
    q->tail = 0;
    q->list_queue_num = 0;
    q->list_queue_end_num = list_queue_len;
    return true;
}

/**
 * @brief 写队列
 * 
 * @param q 队列指针
 * @param p_in_buf 输入
 * @param in_data_len 长度
 * @return true 
 * @return false 
 */
bool list_queue_write(ListQueueStrust * q, uint8_t * p_in_buf, uint16_t in_data_len) 
{
    uint8_t * pbuf = NULL;

    if((in_data_len > LIST_QUEUE_MAX_NUM) || (in_data_len == 0x00))
    {
        return false;
    }
    if((in_data_len + q->list_queue_num) > LIST_QUEUE_MAX_NUM)
    {
        return false;
    }
    uint32_t psr = 0x00;
    uint16_t data_sta = 0x00;
    if(q->list_queue_num < LIST_QUEUE_MAX_NUM)   //如果队列剩余有空间进行入队
    {
        psr = csi_irq_save();
        pbuf = (uint8_t*)&(q->qu[q->tail]);
        for(uint16_t i = 0; i < in_data_len; i++)
        {
            pbuf[data_sta ++] = p_in_buf[i];
            q->tail ++;
            if(q->tail >= LIST_QUEUE_MAX_NUM)
            {
                q->tail = 0;
                pbuf = (uint8_t*)&(q->qu[q->tail]);
                data_sta = 0x00;
            }
            q->list_queue_num ++;
        }
    }
    else
    {
        return false;
    }
    csi_irq_restore(psr);
    return true;
}

/**
 * @brief 读取队列
 * 
 * @param q 队列指针
 * @param p_out_buf 输出buf
 * @param out_data_len 输出长度
 * @return true 返回结果
 * @return false 返回结果
 */
bool list_queue_read(ListQueueStrust * q, uint8_t * p_out_buf, uint16_t out_data_len) 
{
    uint8_t * pbuf;
    if(out_data_len > LIST_QUEUE_MAX_NUM)
    {
        return false;
    }
    if(out_data_len > q->list_queue_num)
    {
        return false;
    }
    uint32_t psr = 0x00;
    uint16_t data_sta = 0x00;
    if(q->list_queue_num > 0)
    {
        psr = csi_irq_save();
        pbuf = (uint8_t*)&q->qu[q->head];
        for(uint16_t i = 0; i < out_data_len; i++)
        {
            p_out_buf[i] = pbuf[data_sta ++];
            q->head ++;
            if(q->head >= LIST_QUEUE_MAX_NUM)
            {
                q->head = 0;
                pbuf = (uint8_t*)&q->qu[q->head];
                data_sta = 0x00;
            }
            q->list_queue_num --;
        }
    }else
    {
        return false;
    }
    csi_irq_restore(psr);
    return true;
}

/**
 * @brief 检查是否进行写flash
 * 
 * @param q 队列指针
 * @return true 不进行写flash
 * @return false 进行写flash操作
 */
uint16_t list_queue_is_full(ListQueueStrust *q)
{
    if((q->list_queue_num) == LIST_QUEUE_MAX_BUF_NUM)
    {
        return 0;
    }
    return q->list_queue_num;
}



// /** \brief  由于48M时钟计算921600波特率有误差，调低内部RC时钟
//  *        默认 0x100 (93.02)   0xF8(92.59)   0xF0(92.08)
//  * 
//  *  \param[in]   none
//  *  \return      None
//  */
// void system_adj_hfosc(void)
// {
// uint32_t reg,irq;

// irq = csi_irq_save();
// reg = SYSCON->CLCR;
// reg &= 0xfffffe00;
// reg |= 0xF0;
// SYSCON->CLCR = reg;
// csi_irq_restore(irq);
// }
